const redis = require("../utils/redis")
const returnOdd = 0.7; //总返奖率
const freeOdd = 0.1
const _ = require("lodash")
const JACKPOT_LV = 0.05

//3 4 5 连自然概率出现的关系
// 3连变成 4连 两端需要1/12的概率 ，中间则为 1/6 整体概率为 5/36 的概率
// 4变5的概率为 3/36分之一  分成36分，则 3：4：5 = 432 ： 60 ： 5
const serviesMultiplier = [432, 60, 5]
// const serviesMultiplier = [1000, 100, 5]

//计算实际概率 通过calImageLv 方法获得，这是固定值，计算好，避免重复值
const multiplierSuccessLines = [
    { image: 1, multiplier: 60, count: 3, lv: 0.0007054884936242022 },
    { image: 1, multiplier: 150, count: 4, lv: 0.00009798451300336142 },
    { image: 1, multiplier: 600, count: 5, lv: 0.000008165376083613452 },
    { image: 2, multiplier: 50, count: 3, lv: 0.0010582327404363033 },
    { image: 2, multiplier: 100, count: 4, lv: 0.00014697676950504212 },
    { image: 2, multiplier: 300, count: 5, lv: 0.000012248064125420177 },
    { image: 3, multiplier: 40, count: 3, lv: 0.0014109769872484043 },
    { image: 3, multiplier: 80, count: 4, lv: 0.00019596902600672284 },
    { image: 3, multiplier: 200, count: 5, lv: 0.000016330752167226904 },
    { image: 4, multiplier: 30, count: 3, lv: 0.0017637212340605053 },
    { image: 4, multiplier: 60, count: 4, lv: 0.0002449612825084035 },
    { image: 4, multiplier: 150, count: 5, lv: 0.00002041344020903363 },
    { image: 5, multiplier: 25, count: 3, lv: 0.0021164654808726066 },
    { image: 5, multiplier: 50, count: 4, lv: 0.00029395353901008424 },
    { image: 5, multiplier: 100, count: 5, lv: 0.000024496128250840355 },
    { image: 6, multiplier: 20, count: 3, lv: 0.002469209727684708 },
    { image: 6, multiplier: 40, count: 4, lv: 0.00034294579551176496 },
    { image: 6, multiplier: 80, count: 5, lv: 0.000028578816292647077 },
    { image: 7, multiplier: 15, count: 3, lv: 0.0028219539744968086 },
    { image: 7, multiplier: 30, count: 4, lv: 0.0003919380520134456 },
    { image: 7, multiplier: 60, count: 5, lv: 0.0000326615043344538 },
    { image: 8, multiplier: 10, count: 3, lv: 0.00317469822130891 },
    { image: 8, multiplier: 20, count: 4, lv: 0.00044093030851512634 },
    { image: 8, multiplier: 40, count: 5, lv: 0.00003674419237626053 },
    { image: 9, multiplier: 5, count: 3, lv: 0.0035274424681210107 },
    { image: 9, multiplier: 10, count: 4, lv: 0.000489922565016807 },
    { image: 9, multiplier: 20, count: 5, lv: 0.00004082688041806726 },
    { image: 1000, multiplier: 100, count: 3, lv: 0.0003527442468121011 },
    { image: 1000, multiplier: 500, count: 4, lv: 0.00004899225650168071 },
    {
      image: 1000,
      multiplier: 1000,
      count: 5,
      lv: 0.000004082688041806726
    },
    { image: 11, multiplier: 0, count: 3, lv: 0 },
    { image: 11, multiplier: 0, count: 4, lv: 0 },
    { image: 11, multiplier: 0, count: 5, lv: 0 },
    { image: 12, multiplier: 0, count: 3, lv: 0.012093726379440665 },
    { image: 12, multiplier: 0, count: 4, lv: 0.0016796842193667592 },
    { image: 12, multiplier: 0, count: 5, lv: 0.00013997368494722993 }
  ]
  
const imageIds = [1,2,3,4,5,6,7,8,9,10,1000,12]

const FREE_GAME = {};

class NinelineModel{
    constructor(){
        this.gameId = 1001;
        this.imageOdds =  [100,100,100,100,100,100,100,100,100,100,100,100]   //没有中奖部分填充概率
        this.line = 9;
    }
    /**
     * 增加房间库存
     */
    async addGameInventory(gems){
        try{
            await redis.hincrbyfloat("game_inventory", this.gameId, gems)
        }catch(err){
            throw err;
        }
    }
    async addJackopt(gems){
        try{
            await redis.hincrbyfloat("game_jackpot", this.gameId, gems)
        }catch(err){
            throw err;
        }
    }
    async getJackpot(){
        try{
            let score = await redis.hget("game_jackpot", this.gameId)
            return +score || 0;
        }catch(err){
            throw err;
        }
    }
    async addPlayerBetAndWins(userId, betGems, wins){
        try{
            await redis.hincrbyfloat("game_user_bet_"+this.gameId, userId, betGems)
            await redis.hincrbyfloat("game_all_bet", this.gameId, betGems)
            await redis.hincrbyfloat("game_user_wins_"+this.gameId, userId, wins)
            await redis.hincrbyfloat("game_all_wins", this.gameId, wins)
        }catch(err){
            throw err;
        }
    }
    async getPlayerAllBet(){
        try{
            let gems = await redis.hget("game_all_bet", this.gameId)
            return +gems;
        }catch(err){
            throw err;
        }
    }
    async getUserAllBetAndTotalWins(userId){
        try{
            let totalBet = await redis.hget("game_user_bet_"+this.gameId, userId)
            let totalWin = await redis.hget("game_user_wins_"+this.gameId, userId)
            let platTotalBet = await redis.hget("game_all_bet",this.gameId)
            let platTotalWin = await redis.hget("game_inventory",this.gameId)
            return {
                totalBet :+totalBet || 0,
                totalWin : +totalWin|| 0,
                platTotalBet: +platTotalBet || 0,
                platTotalWin: +platTotalWin || 0
            };
        }catch(err){
            throw err;
        }
    }
    async clearUserData(userId){
        try{    
            console.log("userId:"+userId)
            await redis.hdel("game_user_bet_"+this.gameId, userId)
            await redis.hdel("game_user_wins_"+this.gameId, userId)
        }catch(err){
            throw err;
        }
    }
    async clearSystemData(){
        await redis.hdel("game_all_bet",this.gameId)
        await redis.hdel("game_inventory",this.gameId)
    }
    async addPlayerFreeCount(userId, freeCount){
        try{
            FREE_GAME.userId = FREE_GAME.userId || 0;
            FREE_GAME.userId += freeCount;
            return;
            await redis.hincrby("game_free_"+this.gameId, userId, freeCount)
        }catch(err){
            throw err;
        }
    }
    async getPlayerFreeCount(userId){
        try{
            return FREE_GAME.userId || 0;
            let freeCount = await redis.hget("game_free_"+this.gameId, userId)
            return +freeCount || 0;
        }catch(err){
            throw err;
        }
    }
    async staticPlayerGame(userId, betGems, wins){
        try{
            let jackpotGems = +(wins * 0.05).toFixed(2);
            let playerWins = wins - jackpotGems;
            let systemWins = betGems - wins;
            await this.addGameInventory(systemWins);
            await this.addJackopt(jackpotGems);
            await this.addPlayerBetAndWins(userId, betGems, playerWins)
        }catch(err){
            throw err;
        }
    }
    async calPlayerY(){
        try{

        }catch(err){
            throw err;
        }
    }

    async calPlayerViewAndResult(playerGameY){
        try{
            //根据玩家控制获取玩家奖励
            let lineResults = await this.calcBetResult(playerGameY);
            lineResults = [
                { line: 1, image: 4, count: 4, multiplier: 60 },
                { line: 8, image: 6, count: 3, multiplier: 20 }
            ]
            let [views, winLineResults] = this.fillWinViews(lineResults) //填充赢的视图
            console.log("------------填充盈利视图--------------")
            console.log(views)
            this.fillWinOtherImage(views, winLineResults, this.imageOdds)  //填充 中奖边界 后面随机出来的这条线就不能连了
            console.log("--------------边界-----------------")
            console.log(views)
            this.fillAllImage(views, winLineResults)  //填充其他部分
            console.log("----------------其他部分-------------")
            this.views = views;
            // this.views = [ [ 7, 1, 1, 6, 7 ], [ 4, 4, 4, 4, 8 ], [ 6, 9, 4, 6, 4 ] ]
            let playerWinResult = this.calResult()
            console.log(views)
            console.log(playerWinResult)
            return playerWinResult
        }catch(err){
            throw err;
        }
    }

    /**
     * @param {*} userId 
     * @param {*} betAmount 
     */
    async startGame(userId, betAmount){
        try{
            let difen = betAmount/9
            let lineResults = await this.calcBetResult(1);  //获得奖励
            let gameFreeFlag = false;
            let freeCount = await this.getPlayerFreeCount(userId);
            if(freeCount>0){
                gameFreeFlag = true;
                // console.log("免费游戏")
                await this.addPlayerFreeCount(userId, -1)
            }
            let [views, winLineResults] = this.fillWinViews(lineResults)
            // await this.handlerJackpot(views, winLineResults)
            // let defaultImageOdds = [100,100,100,100,100,100,100,100,100,100,100,100]
            let imageOdds = [100,100,100,100,100,100,100,100,100,100,100,100];
            //填充没有中奖的部分
            this.fillNotWinImage(views, winLineResults, imageOdds)
            this.fillAllImage(views, imageOdds)
            let playerFreeGameCount = await this.handlerFreeGame(userId, winLineResults);  //处理免费游戏情况
            //计算玩家总盈利
            let totalWinMultiplier = 0, jackpotScore = 0, lineScore = 0;
            for(let {multiplier,image,score} of winLineResults){
                if(image!=1000){
                    totalWinMultiplier += multiplier;
                }else{
                    jackpotScore += score || 0;
                }
            }
            lineScore = totalWinMultiplier * difen;
            let platWinScore = +((gameFreeFlag ? 0: betAmount) - lineScore).toFixed(2)
            //百分之二贡献jackpot
            // let conJackpotScore = +(lineScore* 0.02.toFixed(2))
            let conJackpotScore = 0
            let taxiLineScore = +lineScore
            // await this.addGameInventory(platWinScore)
            // await this.addPlayerBetAndWins(userId, gameFreeFlag ?0: betAmount, taxiLineScore+ jackpotScore)
            return {
                views, 
                result : {
                    freeCount: freeCount + playerFreeGameCount-1 <=0 ? 0 : freeCount + playerFreeGameCount-1,
                    free: gameFreeFlag,
                    wins: {
                        lineScore,
                        taxiLineScore,
                        jackpotScore:0,
                    },
                    winLines: winLineResults,
                },
            }
        }catch(err){
            throw err;
        }
    }
    /**
     * 处理游戏免费情况
     * @param {*} winLineResult 
     */
    async handlerFreeGame(userId, winLineResults){
        try{
            //免费游戏
            let playerFreeGameCount = 0;
            for(let winLineResult of winLineResults){
                if(winLineResult.image == 12){
                    winLineResult.multiplier = 0;
                    if(winLineResult.count == 3){
                        playerFreeGameCount +=1;
                    }
                    if(winLineResult.count == 4){
                        playerFreeGameCount +=3;
                    }
                    if(winLineResult.count == 5){
                        playerFreeGameCount += 5;
                    }
                }
            }
            //增加免费次数
            if(playerFreeGameCount > 0){
                // console.log("----------免费游戏次数增加:"+playerFreeGameCount)
                await this.addPlayerFreeCount(userId, playerFreeGameCount)
            }
            return playerFreeGameCount
        }catch(err){
            throw err;
        }
    }

    async handlerJackpot(views, winLineResuls){
        try{
            let jackpotRandomNumber = Math.random();
            let jackpotCount = 0,winJackpotLv = 0;
            // jackpotRandomNumber = 0.000001
            if(jackpotRandomNumber < JACKPOT_LV) {
                let totalNumber = serviesMultiplier.reduce((prev, cur) => prev+cur);
                let randNumber = Math.random() * totalNumber;
                for(let i = serviesMultiplier.length-1; i>=0; i--){
                    if(randNumber < serviesMultiplier[i]){
                        if(i == 0){
                            winJackpotLv =0.1
                            jackpotCount = 3;
                        }
                        if(i == 2){
                            winJackpotLv =0.2
                            jackpotCount = 4;
                        }
                        if(i == 3){
                            winJackpotLv =0.3
                            jackpotCount = 5;
                        }
                        let line = Math.ceil(Math.random()*9);
                        let left = this.findWinLinePosition(jackpotCount)
                        this.pushPlayerWinsLine(views, winLineResuls, {line:line, image:1000, count:jackpotCount, multiplier:0,left})
                        break;
                    }
                }
            }
        }catch(err){
            throw err;
        }
    }

    /**
     * 填充中奖线的左右位置
     * @param {*} views 
     * @param {*} winLineResuls 
     */
    async fillWinOtherImage(views, winLineResuls, imageOdds){
        try{
            let lineRules = this.getLineRule();
            for(let {line, image, count, left} of winLineResuls){
                let linePositions = lineRules.find((item)=> item.index == line).positions;
                let leftIndex = left -1;  
                let rightIndex = left+count;
                let leftLinePosition = linePositions[leftIndex]
                let rightLinePosition = linePositions[rightIndex]
                if(leftIndex>=0 && views[leftLinePosition[0]][leftLinePosition[1]]==-1){
                    this.fillPositionImage(views, leftLinePosition, imageOdds, [image,1000])
                }
                if(rightIndex<5 && views[rightLinePosition[0]][rightLinePosition[1]]==-1){
                    this.fillPositionImage(views, rightLinePosition, imageOdds, [image,1000])
                }
            }
            return views;
        }catch(err){
            throw err;
        }
    }
    getImageMinSeries(image){
        return 3;
    }
    /**
     * 获取所有连线
     */
    getAllLines(){
        try{
            return [1,2,3,4,5,6,7,8,9]
        }catch(err){
            throw err;
        }
    }
    /**
     * 填充剩余部分,
     * 1,中奖线的位置随便填，因为前面补上了中奖线的左右位置了
     * 2，不中奖的线
     * @param {*} views 
     */
     async fillAllImage(views, winLineResults){
        try{
            let winLines = [], notWinLines = [], allRules = this.getLineRule()
            for(let i = 0; i< winLineResults.length; i++){
                winLines.push(winLineResults[i].line);
            }
            notWinLines = this.getAllLines().filter((item) => !winLines.includes(item))
            //填充中奖线部分
            for(let winLine of winLines){
                let winLinePositions = allRules.find((item) => item.index == winLine).positions;
                for(let position of winLinePositions){
                    if(views[position[0]][position[1]]==-1){
                        this.fillPositionImage(views, position, this.imageOdds, [])
                    }
                }
            }
            //没有中奖部分的
            for(let notWinLine of notWinLines){
                this.calAndFillNotWinLine(views, allRules.find((item) => item.index == notWinLine).positions)
            }
        }catch(err){
            throw err;
        }
     }
     getAllImages(){
        try{
            return [1,2,3,4,5,6,7,8,9,1000,11,12]
        }catch(err){
            throw err;
        }
     }
     /**
      * 根据位置获取这个位置不能替换的图片，如果替换，就会出现连线成功
      * @param {*} views 
      * @param {*} currPosition 肯定是一个-1
      * @returns 
      */
     getNotShowImage(views,  currPosition){
        try{
            // console.log("currPosition", JSON.stringify(currPosition))
            let allImages = this.getAllImages();
            let lineRules = this.getLineRule()
            let notImage  = [];
            //检查所有可能出现的图片，和共线的线，替换是否能让共线的成，如果可以，则不能用这张图片，任何一条线的左边和右边有 1000，那么这个位置不能为1000
            let allLines = this.getAllLines();
            // allLines = [2];
            for(let lineIndex of allLines){
                let lineNotImage = [];  //当前线，当前位置不能出现的图片
                let linePositions = lineRules.find((item) => item.index == lineIndex).positions;  //获取线的位置关系
                let currLinePositionIndex = _.findIndex(linePositions, ([x,y] = item) => x == currPosition[0] && y == currPosition[1]); 
                // console.log("currLinePositionIndex", currLinePositionIndex)
                //找到共存的线，检查共存的线
                // allImages = [2]
                if(currLinePositionIndex !=-1){
                    for(let  t = 0; t< allImages.length; t++){
                        let equalImage = allImages[t]  //如果currPosition 位置替换了这个图片
                        let leftSeriesNumber = 1,rightSeriesNumber = 0;
                        let neighborFlag = true;
                        for(let i = currLinePositionIndex-1; i>=0; i--){
                            let pos = linePositions[i];
                            let viewImage = views[pos[0]][pos[1]]  //已经存在的这个位置的图片
                            // if(viewImage == 1000){
                            //     lineNotImage.push(1000)
                            // }
                            //console.log("xxxx", viewImage, equalImage, neighborFlag, equalImage, leftSeriesNumber)
                            if(viewImage== equalImage || viewImage == 1000 || equalImage==1000){
                                leftSeriesNumber ++;
                               // console.log("进来", viewImage, equalImage, neighborFlag, equalImage, leftSeriesNumber)
                            }else{
                                break;
                            }
                            neighborFlag = false
                        }
                        //console.log("leftSeriesNumber", leftSeriesNumber)
                        let neighborFlag1 = true;
                        for(let i = currLinePositionIndex+1; i< 5; i++){
                            // console.log("j:"+i)
                            let pos = linePositions[i];
                            let viewImage = views[pos[0]][pos[1]] 
                            // console.log("viewImage1:",viewImage)
                            // if(viewImage == 1000){
                            //     lineNotImage.push(1000)
                            // }
                            if(viewImage== equalImage || viewImage == 1000 || equalImage==1000){
                                rightSeriesNumber ++;
                            }else{
                                break;
                            }
                            neighborFlag1 = false;
                        }
                        if((leftSeriesNumber+rightSeriesNumber) >= this.getImageMinSeries(equalImage)){
                            lineNotImage = lineNotImage.concat(equalImage, 1000)
                        }
                    }
                }
                // console.log("几线:"+lineIndex, JSON.stringify(lineNotImage))
                notImage = notImage.concat(lineNotImage)
            }
            notImage = [...new Set(notImage)]
            return notImage;
        }catch(err){
            throw err;
        }
     }
     /**
      * 根据位置获取这个位置不能替换的图片，如果替换，就会出现连线成功
      * @param {*} views 
      * @param {*} currPosition 
      * @returns 
      */
      getNotShowImage2(views,  currPosition){
        try{
            let allImages = this.getAllImages();
            let lineRules = this.getLineRule()
            let notImage  = [];
            let currPositionImage = views[currPosition[0]][currPosition[1]]  //当前位置确定了的图片
            //检查所有可能出现的图片，和共线的线，替换是否能让共线的成，如果可以，则不能用这张图片，任何一条线的左边和右边有 1000，那么这个位置不能为1000
            let allLines = this.getAllLines();
            allLines = [2];
            for(let lineIndex of allLines){
                let lineNotImage = [];  //当前线，当前位置不能出现的图片
                let linePositions = lineRules.find((item) => item.index == lineIndex).positions; 
                let currLinePositionIndex = _.findIndex(linePositions, ([x,y] = item) => x == currPosition[0] && y == currPosition[1]);
                console.log("currLinePositionIndex", currLinePositionIndex)
                //找到共存的线，检查共存的线
                if(currLinePositionIndex !=-1){
                    let leftSeriesNumber = 1,rightSeriesNumber = 0;
                    let neighborFlag = true;
                    for(let i = currLinePositionIndex-1; i>=0; i--){
                        console.log("i:"+i)
                        let pos = linePositions[i];
                        let viewImage = views[pos[0]][pos[1]]  //已经存在的这个位置的图片
                        if(viewImage== currPositionImage || viewImage == 1000 || (currPositionImage==1000 && neighborFlag)){
                            leftSeriesNumber ++;
                        }else{
                            break;
                        }
                        neighborFlag = false;
                    }
                    let neighborFlag1 = true;
                    for(let i = currLinePositionIndex+1; i< 5; i++){
                        console.log("j:"+i)
                        let pos = linePositions[i];
                        let viewImage = views[pos[0]][pos[1]] 
                        if(viewImage== currPositionImage || viewImage == 1000 || (currPositionImage==1000 && neighborFlag1)){
                            rightSeriesNumber ++;
                        }else{
                            break;
                        }
                        neighborFlag1 = false;
                    }
                    if((leftSeriesNumber+rightSeriesNumber) >= this.getImageMinSeries(equalImage)-1){
                        console.log("-------------"+equalImage)
                        lineNotImage = lineNotImage.concat(equalImage, 1000)
                    }
                }
                console.log("几线:"+lineIndex, JSON.stringify(lineNotImage))
                notImage = notImage.concat(lineNotImage)
            }
            notImage = [...new Set(notImage)]
            return notImage;
        }catch(err){
            throw err;
        }
     }
     /**
      * 指定线随机生成不能中奖，
      * 1.找到第一个为 -1的图片，看左边的图片有几个连续，填充自己不超过最大连续数量
      * 2.向右找到 -1的位置，检查左1连续次数，右边不能超过最大可连
      * @param {*} views 
      * @param {*} positions 
      */
      calAndFillNotWinLine(views, positions){
        try{
            // console.log("---------避免死循环判断--------------")
            let firstIndex = _.findIndex(positions, ([x,y] = item) => views[x][y] == -1);
            if(firstIndex ==-1){
                return;
            }
            // console.log("before:",JSON.stringify(views))
            let notImage = this.getNotShowImage(views, positions[firstIndex])
            this.fillPositionImage(views, positions[firstIndex], this.imageOdds, notImage)
            // console.log("after:",JSON.stringify(views), JSON.stringify(notImage), JSON.stringify(positions))
            this.calAndFillNotWinLine(views, positions)  //继续递归
        }catch(err){
            throw err;
        }
     }

    /**
     * 填充一个位置
     * @param {*} views 
     * @param {*} position 
     * @param {*} imageOddLvs 
     * @param {*} notImages  不能为这些图片
     */
    fillPositionImage(views, position, imageOdds, notImages){
        try{
            let cloneOdds = _.clone(imageOdds)
            let allImages = this.getAllImages();
            for(let i = 0; i< cloneOdds.length;i++){
                if(notImages.includes(allImages[i])){
                    cloneOdds[i]= 0;
                }
            }
            let oddLvs = [],currMaxLv = 0;
            for(let i = 0; i< cloneOdds.length; i++){
                oddLvs.push([currMaxLv, currMaxLv+cloneOdds[i]])
                currMaxLv += cloneOdds[i]
            }  
            let totalPotLv = cloneOdds.reduce((prev, cur) => prev+cur);
            let mathRandnumber = Math.random() * totalPotLv;
            let succcessImage = 0;
            for(let i = 0; i< oddLvs.length; i++){
                let [min,max] = oddLvs[i]
                if(mathRandnumber>=min && mathRandnumber<= max){
                    succcessImage = allImages[i];
                    break;
                }
            }
            views[position[0]][position[1]] = succcessImage;
        }catch(err){
            throw err;
        }
    }

    //获取连线规则
    getLineRule(){
        return [
            {positions:[[1,0],[1,1],[1,2],[1,3],[1,4]],index:1}, //L1
            {positions:[[0,0],[0,1],[0,2],[0,3],[0,4]],index:2}, //L2
            {positions:[[2,0],[2,1],[2,2],[2,3],[2,4]],index:3}, //L3
            {positions:[[0,0],[1,1],[2,2],[1,3],[0,4]],index:4}, //L4
            {positions:[[2,0],[1,1],[0,2],[1,3],[2,4]],index:5}, //L5
            {positions:[[1,0],[0,1],[0,2],[0,3],[1,4]],index:6}, //L6
            {positions:[[1,0],[2,1],[2,2],[2,3],[1,4]],index:7}, //L7
            {positions:[[0,0],[0,1],[1,2],[2,3],[2,4]],index:8}, //L8
            {positions:[[2,0],[2,1],[1,2],[0,3],[0,4]],index:9}, //L9
        ]
    }

    /**
     * 检查这个positionIndex 在 这条线上是否存在其他图片了，如果存在，返回true
     * @param {*} views 
     * @param {*} linePositions 
     * @param {*} positionIndex 
     * @param {*} image 
     */
    checkPositionImage(views, linePositions, positionIndex, image){
        try{
            let positions = linePositions[positionIndex];
            let targetImage = views[positions[0]][positions[1]]
            if(targetImage != image && targetImage!=-1){
                return true;
            }
            return false;
        }catch(err){
            throw err;
        }
    }

    /**
     * 给生成中间的一条线找到合适的位置，优先中奖的线，如果找不到，这条线忽略
     * @param {*} views 
     * @param {*} lineResult 
     */
    findWinLinePosition(count){
        try{
            let marginList = [];
            if(count ==2){
                marginList  = [0,3]
            }
            if(count ==3){
                marginList  = [0,2]
            }
            if(count ==4){
                marginList  = [0,1]
            }
            let left = marginList[Math.floor(Math.random()* marginList.length)]
            return left;
        }catch(err){
            throw err;
        }
    }

    /**
     * 
     * @param {*} views 
     * @param {*} winLineResuls 
     * @param {*} param2 
     * @param {*} param2 
     */
    pushPlayerWinsLine(views, winLineResuls, {line, image, count, multiplier, left} = lineResult){
        try{
            let lineRules = this.getLineRule();
            let linePositions = lineRules.find((item) => item.index == line).positions
            for(let i = left; i<left+count; i++){
                let position = linePositions[i];
                views[position[0]][position[1]] = image;
                //有概率替补钻石位
                let dialondLv = this.getImageAppearLv(9);
                if(Math.random() < dialondLv){
                    views[position[0]][position[1]] = 1000;
                }
            }
            let winline = {line, image, count, multiplier, left} 
            winLineResuls.push(winline);
        }catch(err){
            throw err;
        }
    }

    /**
     * 获得指定图片出现的概率
     * @param {*} image 
     */
    getImageAppearLv(imageIndex){
        try{
            let totalLv = this.imageOdds.reduce((prev, cur) => prev+cur);
            let imageOdd = this.imageOdds[imageIndex];
            return imageOdd/totalLv
        }catch(err){
            throw err;
        }
    }

    /**
     * 根据奖励来填充奖励视图
     * @param {*} lineResults 
     */
    fillWinViews(lineResults){
        try{
            let allLineIndexs = this.getAllLines()
            let views = [[-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1]]
            let winLineResuls = [];
            for(let {image, count, multiplier} of lineResults){
                let left = this.findWinLinePosition(count);
                //占线了,再找别的可以用的线
                if(allLineIndexs.length == 0){
                    return [views, winLineResuls]
                }
                let line = allLineIndexs[Math.floor(Math.random() * allLineIndexs.length)]
                let lineIndex = allLineIndexs.indexOf(line)
                allLineIndexs.splice(lineIndex, 1);
                this.pushPlayerWinsLine(views, winLineResuls, {line, image, count, multiplier,left})
            }
            return [views, winLineResuls]
        }catch(err){
            throw err;
        }
    }

    /**
     * 根据玩家Y值计算玩家中奖
     * 9条线，给9次机会，如果一次机会
     * @param {*} playerGameY 
     */
    async calcBetResult(playerGameY){
        try{
            let playerWinLines  = []; //玩家成功连线列表， line 几线， image 图片 count 几个 multiple 赔率
            for(let i = 1; i<= 9; i++){
                for(let j = 0; j< multiplierSuccessLines.length; j++){  //每个连线都有一次机会
                    let randNumber = Math.random();
                    if(randNumber < multiplierSuccessLines[j].lv * playerGameY){
                        playerWinLines.push({
                            image: multiplierSuccessLines[j].image,
                            count: multiplierSuccessLines[j].count,
                            multiplier:multiplierSuccessLines[j].multiplier
                        })
                    }
                }   
            }
            return playerWinLines
        }catch(err){
            throw err;
        }
    }
    calResult(){
        try{
            let result = [];
            let linesConfigs = this.getLineRule();
            let winLines = linesConfigs.slice(0, this.line);
            for(let lineItem of winLines){
                let [winFlag,winObj] = this.checkWinLine(lineItem)
                if(winFlag){
                    result.push(winObj)
                }
            } 
            return result;
        }catch(err){
            throw err;
        }
    }
    /**
     * 根据poker找到对应的奖励规则
     * @param {*} selectPoker 
     * @param {*} pokerNumber 
     */
    getPokerOdds(selectPoker, pokerNumber){
        try{
            let winLineItem = multiplierSuccessLines.find((item) => item.image == selectPoker && item.count == pokerNumber)
            return winLineItem;
        }catch(err){
            throw err;
        }
    }
    /**
     * 检查这行是否是赢得
     * @param {*} winLineItem {line:[[0,0],[0,1],[0,2],[0,3],[0,4]],type:1}, //L1  type=1横向
     */
     checkWinLine(winLineItem){
        try{
            //得到这条线所有的牌
            let linePokers = [];
            for(let [h,l] of winLineItem.positions){
                linePokers.push(this.views[h][l]);
            }
            let results = checkLine.call(this, linePokers);
            linePokers = linePokers.reverse();
            results = results.concat(checkLine.call(this, linePokers, true))
            if(results.length ==0){
                return [false]
            }
            //找到最大倍数的
            let maxBet = -1,maxItem = null;
            for(let i = 0; i< results.length; i++){
                let {multiplier, poker} = results[i]
                if(maxBet<multiplier){
                    maxItem = results[i];
                    maxBet = multiplier;
                }
                if(poker ==12){
                    maxItem = results[i];
                    maxBet = multiplier;
                    break;
                }
            }
            return [true, maxItem]
            function checkLine(linePokers,fanxiang){
                let results = [];
                let selectPoker = linePokers[0];
                //检查有多少个1000连线
                if(selectPoker == "1000"){
                    let indexs = []
                    let baidaiNumber = 0;
                    for(let i= 0; i < linePokers.length; i++){
                        if(linePokers[i] == "1000"){
                            baidaiNumber++;
                            if(fanxiang){
                                indexs.push(winLineItem.positions[4-i])
                            }else{
                                indexs.push(winLineItem.positions[i])
                            }
                        }else{
                            break;
                        }
                    }
                    let oddItem = this.getPokerOdds(selectPoker, baidaiNumber)
                    if(oddItem){
                        results.push({
                            pos:indexs,
                            line:winLineItem.index,
                            ...oddItem
                        })
                    }
                }
                let indexs = [], pokerNumber =0;
                //从左往右，找到一个不为白搭牌的第一个
                for(let i= 0; i < linePokers.length; i++){
                    if(linePokers[i]!= 1000){
                        selectPoker = linePokers[i];
                        pokerNumber = i+1;
                        if(fanxiang){
                            indexs.push(winLineItem.positions[4-i])
                        }else{
                            indexs.push(winLineItem.positions[i])
                        }
                        //jackpot不可连万能牌
                        if(selectPoker == 12){
                            pokerNumber =1;
                            if(fanxiang){
                                indexs = [winLineItem.positions[4-i]];
                            }else{
                                indexs = [winLineItem.positions[i]];
                            }
                        }
                        // console.log(winLineItem)
                        for(let j =i+1; j< linePokers.length; j++){
                            if(selectPoker == linePokers[j] || (linePokers[j]=="1000" && selectPoker!=12)){
                                pokerNumber++;
                                if(fanxiang){
                                    indexs.push(winLineItem.positions[4-j])
                                }else{
                                    indexs.push(winLineItem.positions[j])
                                }
                            }else{
                                break;
                            }
                        }
                        break;
                    }else{
                        if(fanxiang){
                            indexs.push(winLineItem.positions[4-i])
                        }else{
                            indexs.push(winLineItem.positions[i])
                        }
                    }
                }
                let oddItem = this.getPokerOdds(selectPoker, pokerNumber)
                if(oddItem){
                    results.push({
                        pos:indexs,
                        line:winLineItem.index,
                        ...oddItem
                    })
                }
                return results;
            }
        }catch(err){
            throw err;
        }
    }

    /**
     * 计算各个图片出现的概率，计算完替换multiplierLines，用计算好的lv来算玩家中奖
     */
     calImageLv(){
        try{
            //玩家奖金分布由后台配置读取, 每个图片对应一个，3叶草和jackpot除外
            let serverBounsDistribution = [1, 1.5 ,2 ,2.5 ,3 ,3.5 ,4, 4.5 ,5, 0.5]
            let bounsDistribution = [];
            for(let serverBoun of serverBounsDistribution){
                bounsDistribution = bounsDistribution.concat([serverBoun, serverBoun, serverBoun])
            }
           
            let potLineLvs = [];
            for(let i = 0; i< bounsDistribution.length; i++){
                potLineLvs[i] = bounsDistribution[i]* serviesMultiplier[i%3] * multiplierSuccessLines[i].multiplier
            }
            let totalPotLv = potLineLvs.reduce((prev, cur) => prev+cur);
            for(let i = 0; i < multiplierSuccessLines.length; i++){
                multiplierSuccessLines[i].lv = potLineLvs[i]/totalPotLv/multiplierSuccessLines[i].multiplier * (returnOdd - freeOdd)
            }
            //免费游戏计算，一次免费游戏相当于白送一个本金，相当于9倍返奖，  3次 27倍 5次 45倍  总共   
            //考虑免费游戏 再转 最终返奖70%的情况，/0.55经过千万数据跑得到的结果
            //serviesMultiplier 是出现的概率，下面还得乘以份额，得到具体的数学概率
            let freePotOdds =  _.clone(serviesMultiplier);
            let equalDivision = [9, 18, 27]
            for(let i =0; i< freePotOdds.length; i++){
                freePotOdds[i] *= equalDivision[i];
            }
            let freetTotalPotLv = freePotOdds.reduce((prev, cur) => prev+cur);
            multiplierSuccessLines[30].lv =  freePotOdds[0]/freetTotalPotLv/ (9*returnOdd) * freeOdd  //(9*(returnOdd - freeOdd)) 9倍返奖，但是实际返奖只有0.6，所以还要*0.6
            multiplierSuccessLines[31].lv =  freePotOdds[1]/freetTotalPotLv/ (18*returnOdd)  * freeOdd 
            multiplierSuccessLines[32].lv =  freePotOdds[2]/freetTotalPotLv/ (27*returnOdd)  * freeOdd 
            console.log(multiplierSuccessLines)
        }catch(err){
            throw err;
        }
    }
}

module.exports = NinelineModel